package org.itboys.product.search;

import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.common.SolrInputDocument;
import org.itboys.framework.query.Page;
import org.itboys.product.dto.ProductDTO;
import org.itboys.solr.client.SolrClient;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 商品搜索
 */
public class ProductSearchService implements InitializingBean {

    /**
     * 批量构建每次发多少个文档
     */
    private static final int MAX_BUILD_DOCS = 100;

    @Resource(name = "productSolrClient")
    private SolrClient productSolrClient;

    private int coreSize;

    /**
     * 线程池
     */
    private ExecutorService solrExecutor;

    /**
     * 构建商品搜索文档
     * @param productSearchDocs 可传 一个 或多个 或数组 的商品文档
     */
    public void buildProductSearchIndex(ProductSearchDoc ...productSearchDocs) {
        if (ArrayUtils.isEmpty(productSearchDocs)) {
            return;
        }
        buildProductSearchIndex(Lists.newArrayList(productSearchDocs));
    }

    /**
     * 批量构建商品搜索文档
     * @param productSearchDocs
     */
    public void buildProductSearchIndex(List<ProductSearchDoc> productSearchDocs) {
        if (CollectionUtils.isEmpty(productSearchDocs)){
            return;
        }
        List<SolrInputDocument> docs = Lists.newArrayList();
        productSearchDocs.forEach(productSearchDoc -> {
            SolrInputDocument doc = new SolrInputDocument();
            doc.addField(ProductSearchDoc.FIELD_PRODUCT_ID, productSearchDoc.getProductId());
            doc.addField(ProductSearchDoc.FIELD_PRODUCT_NAME,productSearchDoc.getProductName());
            doc.addField(ProductSearchDoc.FIELD_SHOP_ID, productSearchDoc.getShopId());
            doc.addField(ProductSearchDoc.FIELD_BRAND_ID, productSearchDoc.getBrandId());
            doc.addField(ProductSearchDoc.FIELD_CATEGORY_FULL_ID, productSearchDoc.getCategoryFullIdPath());
            doc.addField(ProductSearchDoc.FIELD_PRICE, productSearchDoc.getPrice());
            docs.add(doc);
            if (MAX_BUILD_DOCS == docs.size()) {
                doBuildProductSearchIndex(docs);
                docs.clear();
            }
        });
        if (CollectionUtils.isNotEmpty(docs)) {
            doBuildProductSearchIndex(docs);
        }
    }

    /**
     * 根据条件分页搜索 并返回排好序的搜索结果商品ID
     * @param searchParam
     * @return
     */
    public Page<Long> searchAndReturnProductIds(ProductSearchParam searchParam) {
        //TODO 先只根据关键词搜索 后面有其他排序search条件
        StringBuilder sb = new StringBuilder("product_name").append(":").append(searchParam.getKeyword());
        String queryString = sb.toString();
        SolrQuery solrQuery = new SolrQuery(queryString);
        solrQuery.setStart((searchParam.getPageNo() - 1) * searchParam.getPageSize());
        solrQuery.setRows(searchParam.getPageSize());
        Page<Long> page = productSolrClient.pageQuery(solrQuery, doc -> (Long) doc.get(ProductSearchDoc.FIELD_PRODUCT_ID));
        page.setPageNo(searchParam.getPageNo());
        page.setPageSize(searchParam.getPageSize());
        return page;
    }

    /**
     * 分页搜索商品并返回商品DTO
     * @return
     */
    /*public Page<ProductDTO> pageSearchProduct(ProductSearchParam searchParam) {
        Page<Long> idPage = searchAndReturnProductIds(searchParam);
        if (idPage == null) {
            return null;
        }
        if (CollectionUtils.isEmpty(idPage.getResult())) {
            return new Page<>();
        }
        List<ProductDTO> productDTOs = productLoader.getValues(idPage.getResult());
        return new Page<>(productDTOs, searchParam.getPageNo(), searchParam.getPageSize(), idPage.getTotalCount());
    }*/

    private void doBuildProductSearchIndex(List<SolrInputDocument> docs) {
        solrExecutor.submit(() -> productSolrClient.addSolrInputDocuments(docs));
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        solrExecutor = Executors.newFixedThreadPool(coreSize);
    }

    public void setCoreSize(int coreSize) {
        this.coreSize = coreSize;
    }

}
